template <class VC>
ClippingPoly::ClippingPoly ( const std::vector< VC >& vec ):
	l ( vec.size() )
{
	for ( int i = 0; i < size(); ++i ){
		l[i]( vec[i].coord,vec[(i + 1) % size()].coord );
		center += vec[i].coord;
	}
	center /= (float) size();
}


template <class VC>
std::vector< VC > ClippingPoly::clipInclusively ( const std::vector< VC >& passed ){
	std::vector < VC > tmp;
	tmp.reserve(4);
	std::vector < VC > r = passed;
	
	bool lastIn,currIn;
	int nClipLines = l.size();
	int nClipPoints = passed.size();
	
	for ( int i = 0; i < nClipLines; ++i ){
		float ccenter = l[i].compare( center );
		lastIn = sameSignX ( l[i].compare( r[0].coord ), ccenter );

		bool anyOut = false;
		
		
		for ( int iq = 1; iq < nClipPoints + 1; ++iq ){
			int q = iq % nClipPoints;
			currIn = sameSignX ( l[i].compare( r[q].coord ), ccenter );
			
			if ( currIn ){
				if ( ! lastIn ){
					VC tmp_vertex = r[q] - r[iq - 1];
					Vertex3f& deltav = tmp_vertex.coord;
					Vertex3f omegav = Line::intersection( r[q].coord, r[iq - 1].coord, l[i] ) - r[iq - 1].coord;
					float f = 0.0;
					if ( fabsf( deltav.x() ) > 0.0001 ){ f = omegav.x() / deltav.x(); }
					else if ( fabsf( deltav.y() ) > 0.0001 ){ f = omegav.y() / deltav.y(); }
					else if ( fabsf( deltav.z() ) > 0.0001 ){ f = omegav.z() / deltav.z(); }
					
					tmp.push_back( r[iq - 1] + tmp_vertex * f );
				}
				tmp.push_back( r[q] );
			}
			else{
				anyOut = true;
				if ( lastIn ){
					VC tmp_vertex = r[q] - r[iq - 1];
					Vertex3f& deltav = tmp_vertex.coord;
					Vertex3f omegav = Line::intersection( r[q].coord, r[iq - 1].coord, l[i] ) - r[iq - 1].coord;
					float f = 0.0;
					if ( fabsf( deltav.x() ) > 0.0001 ){ f = omegav.x() / deltav.x(); }
					else if ( fabsf( deltav.y() ) > 0.0001 ){ f = omegav.y() / deltav.y(); }
					else if ( fabsf( deltav.z() ) > 0.0001 ){ f = omegav.z() / deltav.z(); }
					
					tmp.push_back( r[iq - 1] + tmp_vertex * f );
				}
			}
			
			lastIn = currIn;
		}
		
		if ( anyOut ){
			r = tmp;
			nClipPoints = r.size();
			if ( nClipPoints < 3 ){ return std::vector<VC>(); }
		}
		tmp.clear();
	}
	return r;
}





template < class VC >
void ClippingPoly::clipExclusively ( const std::vector< VC >& passed, std::vector < std::vector< VC > >& ret ){

	
	int nClipLines = size();
	int nClipPoints = passed.size();

//	Line checkLines[nClipPoints];
//	Vertex3f checkCenter;
//	for ( int i = 0; i < nClipPoints; ++i ){
//		checkLines[i] = Line( passed[i].coord, passed[(i + 1) % nClipPoints].coord );
//		checkCenter += passed[i].coord;
//	}
//	checkCenter /= (float) nClipPoints;
//	
//	{
//		bool discardTest = true;
//		for ( int i = 0; i < size(); ++i ){
//			bool allIn = true;
//			for ( int j = 0; j < nClipPoints; ++j ){
//				if ( ! sameSignX( checkLines[j].compare( l[i].p[0] ), checkLines[j].compare( checkCenter ) ) ){ allIn = false;break; }
//			}
//			if ( allIn ){ discardTest = false;break; }
//		}
//		
//		if ( discardTest ){ ret.push_back( passed );return; }
//	}
	
	std::vector < VC > r = passed;
	std::vector < VC > newR;
	std::vector < VC > tmp;
	
	for ( int i = 0; i < nClipLines; ++i ){
		float comparisons[ nClipPoints ];
		bool ins[ nClipPoints ];
		float centerComparison = l[i].compare( center );
		int nout = 0;
		
		
		for ( int j = 0; j < nClipPoints; ++j ){
			comparisons[j] = l[i].compare( r[j].coord );
			if ( fabsf( comparisons[j] ) < 0.001 ){ comparisons[j] = 0.0; }
			ins[j] = sameSign( comparisons[j], centerComparison );
			if ( ! ins[j] ){ ++nout; }
		}
		 
		 
		if ( nout == 0 ){
			continue;
		}
		else if ( nout == nClipPoints ){
			ret.push_back( r );
			return;
		}
		else{
			
			for ( int q = 0; q < nClipPoints; ++q ){
				int lastq = q - 1;
				if ( lastq < 0 ){ lastq = nClipPoints - 1; }
				
				bool currentIn = ins[q];
				bool lastIn = ins[lastq];
				
				if ( currentIn ){
					if ( lastIn ){
						newR.push_back( r[q] );
					}
					else if ( ! lastIn ){
						VC tmp_vertex = r[q] - r[lastq];
						Vertex3f& deltav = tmp_vertex.coord;
						Vertex3f omegav = Line::intersection( r[q].coord, r[lastq].coord, l[i] ) - r[lastq].coord;
						float f = 0.0;
						if ( fabsf( deltav.x() ) > 0.0001 ){ f = omegav.x() / deltav.x(); }
						else if ( fabsf( deltav.y() ) > 0.0001 ){ f = omegav.y() / deltav.y(); }
						else if ( fabsf( deltav.z() ) > 0.0001 ){ f = omegav.z() / deltav.z(); }
						
						newR.push_back( r[lastq] + tmp_vertex * f );
						
						tmp.push_back( newR.back() );
						
						newR.push_back( r[q] );
					}
				}
				else if ( ! currentIn ){
					if ( lastIn ){
						VC tmp_vertex = r[q] - r[lastq];
						Vertex3f& deltav = tmp_vertex.coord;
						Vertex3f omegav = Line::intersection( r[q].coord, r[lastq].coord, l[i] ) - r[lastq].coord;
						float f = 0.0;
						if ( fabsf( deltav.x() ) > 0.0001 ){ f = omegav.x() / deltav.x(); }
						else if ( fabsf( deltav.y() ) > 0.0001 ){ f = omegav.y() / deltav.y(); }
						else if ( fabsf( deltav.z() ) > 0.0001 ){ f = omegav.z() / deltav.z(); }
						
						newR.push_back( r[lastq] + tmp_vertex * f );
						
						tmp.push_back( newR.back() );
						
						tmp.push_back( r[q] );
					}
					else if ( ! lastIn ){
						tmp.push_back( r[q] );
					}
				}
				
				
				
			}
			ret.push_back( tmp );
			tmp.clear();
			r = newR;
			nClipPoints = r.size();
			newR.clear();
			
		}
	}
}
